import random
from time import sleep
import json
import logging
import asyncio
_LOGGER = logging.getLogger(__name__)
from homeassistant.helpers.json import JSONEncoder
from abc import abstractmethod
from .const import (sub_topic, sub_topic_ha, pub_topic, CONF_BROKER,
                    CONF_BROKER_PORT)


class MqttClient(object):
    def __init__(self, hass, username, password,uid) -> None:
        self.broker = CONF_BROKER
        self.port = CONF_BROKER_PORT
        self.username = username
        self.password = password
        self.topic = sub_topic + username + "/#"
        self.topic_ha = sub_topic_ha + username + "/#"
        self.client_id = uid
        self.client = None
        self._hass = hass
        self._event = None
        self.flag = False
        self.init()

    def init(self):
        from paho.mqtt import client as mqtt_client
        self.client = mqtt_client.Client(self.client_id)
        self.client.username_pw_set(self.username, self.password)
        self.client.on_connect = self.on_connect
        self.client.on_disconnect = self.on_disconnect

    def on_connect(self, client, userdata, flags, rc):
        self.client.subscribe(self.topic)
        self.client.subscribe(self.topic_ha)
        self.client.on_message = self.on_message
        self.flag = True
        if rc == 0:
            _LOGGER.warning("云平台连接成功")
            self._hass.states.set("smarthome_voice_assistant.state", "success")
            
        else:
            _LOGGER.error('云平台连接失败')
            self._hass.states.set("smarthome_voice_assistant.state", "error")

    def on_disconnect(self, client, userdata, rc):
        _LOGGER.warning('云平台断开连接')
        self._hass.states.set("smarthome_voice_assistant.state", "fail")

    async def start(self):
        try:
            result = await self._hass.async_add_executor_job(
                    self.client.connect,
                    self.broker, 
                    self.port, 
                    30
                )
            self.client.loop_start()
        except Exception as e:
            _LOGGER.error('云平台连接错误：',e)
            self._hass.states.async_set("smarthome_voice_assistant.state", "error")
            await asyncio.sleep(3)
            await self.start()

    async def stop(self):
        await self._hass.async_add_executor_job(self.client.disconnect)
        await self._hass.async_add_executor_job(self.client.loop_stop)
        self.flag = False

    def json_loads(self, msg):
        return json.loads(
            json.dumps(msg, sort_keys=True, cls=JSONEncoder).encode('UTF-8')
        )

    async def publish(self,payload,topic=None):
        s = json.dumps(payload, sort_keys=True, cls=JSONEncoder).encode('UTF-8')
        if topic == None:
            topic = pub_topic + self.username
        await self._hass.async_add_executor_job(self.client.publish,topic, s)

    @abstractmethod
    def on_message(self, client, userdata, msg):
        pass
